package com.deep.deepenterpise.service.unit.impl;

import com.deep.deepenterpise.common.DrGson;
import com.deep.deepenterpise.common.DrTransactionCommon;
import com.deep.deepenterpise.common.code.DrCodeMsg;
import com.deep.deepenterpise.common.enums.*;
import com.deep.deepenterpise.common.lock.DrLockConstants;
import com.deep.deepenterpise.common.lock.DrLockService;
import com.deep.deepenterpise.common.page.DrPageHelper;
import com.deep.deepenterpise.common.result.DrResult;
import com.deep.deepenterpise.common.util.DrDateUtil;
import com.deep.deepenterpise.dao.*;
import com.deep.deepenterpise.model.bo.DrMemberBo;
import com.deep.deepenterpise.model.bo.DrUserInfoBo;
import com.deep.deepenterpise.model.entity.DrCheckHistory;
import com.deep.deepenterpise.model.entity.DrDangerHistory;
import com.deep.deepenterpise.model.entity.DrGoodsOrder;
import com.deep.deepenterpise.model.to.unit.*;
import com.deep.deepenterpise.model.vo.DrPageBaseVo;
import com.deep.deepenterpise.model.vo.unit.*;
import com.deep.deepenterpise.service.unit.IDrCheckService;
import com.deep.deepenterpise.service.unit.IDrDangerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author xyz
 * @version 1.0
 * @title DrCheckServiceImpl
 * @description
 * @create 2024/6/13 13:42
 */
@Service
@Slf4j
public class DrCheckServiceImpl implements IDrCheckService {
    @Resource
    private DrCheckItemMapper drCheckItemMapper;
    @Resource
    private DrSysUserMapper drSysUserMapper;
    @Resource
    private DrGoodsOrderMapper drGoodsOrderMapper;
    @Resource
    private DrLockService drLockService;
    @Resource
    private DrDangerHistoryMapper drDangerHistoryMapper;
    @Resource
    private DrSysMemberMapper drSysMemberMapper;
    @Resource
    private IDrDangerService iDrDangerService;
    @Resource
    private DrTransactionCommon drTransactionCommon;
    @Resource
    private DrCheckHistoryMapper drCheckHistoryMapper;

    /**
     * @return com.deep.deepenterpise.common.result.DrResult
     * @Auth xyz
     * @Desc //TODO 获取入户检查项
     * @Param [drUserUuid]
     * @Time 14:02 2024/6/13
     */
    @Override
    public DrResult getDrCheckHouseItem(String drUserUuid) {
        String drUnitKey = drSysUserMapper.findDrUnitKeyByDrUserUuidAndDrStatus(drUserUuid, DrStateEnum.YES.getDrState());
        if (StringUtils.isBlank(drUnitKey)) {
            return DrResult.error().message("用户不存在");
        }
        List<DrUnitCheckItemVo> drUnitCheckItemVos = drCheckItemMapper
                .findByDrCategoryAndDrStatus(DrCategoryEnum.CHECK_HOUSE.getDrType(), DrStateEnum.YES.getDrState());
        return DrResult.ok().data(drUnitCheckItemVos);
    }

    /**
     * @return com.deep.deepenterpise.common.result.DrResult
     * @Auth xyz
     * @Desc //TODO 获取隐患子状态
     * @Time 21:12 2024/6/24
     */
    @Override
    public DrResult getDrDangerSlaveStatus() {
        List<DrDangerSlaveStatusVo> drDangerSlaveStatusVos = new ArrayList<>(DrDangerSlaveEnum.values().length);
        for (DrDangerSlaveEnum value : DrDangerSlaveEnum.values()) {
            drDangerSlaveStatusVos.add(new DrDangerSlaveStatusVo(value.getDrState(), value.getValue()));
        }
        return DrResult.ok().data(drDangerSlaveStatusVos);
    }

    /**
     * @return com.deep.deepenterpise.common.result.DrResult
     * @Auth xyz
     * @Desc //TODO 查询是否是首次入户安检
     * @Time 15:43 2024/6/22
     * @Param [drCheckFirstTo]
     */
    @Override
    public DrResult postDrCheckHouseFirst(DrCheckFirstTo drCheckFirstTo) {
        Long num = drGoodsOrderMapper
                .countByDrMemberIdAndDrOrderTypeAndDrFirst(drCheckFirstTo.getDrMemberId(),
                        DrOrderTypeEnum.CHECK_HOUSE.getDrType(), DrStateEnum.YES.getDrState());
        int drCheck = num != null && num > 0 ? 1 : 0;
        return DrResult.ok().data(drCheck);
    }

    /**
     * @return com.deep.deepenterpise.common.result.DrResult
     * @Auth xyz
     * @Desc //TODO 提交入户检查项
     * @Time 21:46 2024/6/13
     * @Param [drUserUuid, drCheckHousePutTo]
     */
    @Override
    public DrResult postDrCheckHousePut(String drUserUuid, DrCheckHousePutTo drCheckHousePutTo) {
        DrUserInfoBo drUserInfoBo = drSysUserMapper.findByDrUserUuidAndDrStatus(drUserUuid, DrStateEnum.YES.getDrState());
        if (drUserInfoBo == null) {
            return DrResult.error().message("员工不存在或状态异常");
        }
        return drLockService.executeWithLock(DrLockConstants.UPDATE_ORDER_LOCK + drCheckHousePutTo.getDrMasterOrderNum(),
                6, TimeUnit.SECONDS,
                () -> putCheckOrder(drUserInfoBo, drCheckHousePutTo));
    }

    /**
     * @return com.deep.deepenterpise.common.result.DrResult
     * @Auth xyz
     * @Desc //TODO 提交入户检查项
     * @Time 21:55 2024/6/13
     * @Param [drUserUuid, drUnitKey, drCheckHousePutTo]
     */
    private DrResult putCheckOrder(DrUserInfoBo drUserInfoBo, DrCheckHousePutTo drCheckHousePutTo) {
        DrGoodsOrder drGoodsOrder = drGoodsOrderMapper.findByDrMasterOrderNum(drCheckHousePutTo.getDrMasterOrderNum());
        if (drGoodsOrder == null) {
            return DrResult.error("订单不存在");
        }

        if (DrSecurityEnum.YES.compare(drGoodsOrder.getDrSecurity())) {
            return DrResult.error("订单已完成");
        }

        DrMemberBo drMemberBo = drSysMemberMapper.findByDrMemberId(Integer.parseInt(drGoodsOrder.getDrMemberId()));
        if (drMemberBo == null) {
            return DrResult.error("会员信息不存在");
        }

        List<DrUnitCheckItemVo> drCheckItemVos = drCheckItemMapper
                .findByDrCategoryAndDrStatus(DrCategoryEnum.CHECK_HOUSE.getDrType(), DrStateEnum.YES.getDrState());
        if (CollectionUtils.isEmpty(drCheckItemVos)) {
            return DrResult.error("获取安检项失败");
        }
        drMemberBo.setDrAddress(drGoodsOrder.getDrAddressDetail());

        long currentSeconds = DrDateUtil.getCurrentSeconds();
        String drOrderNum = DrOrderTypeEnum.CHECK_HOUSE.getDrCode() + currentSeconds;
        return drLockService.executeWithLock(DrLockConstants.CREATE_CHECK_HISTORY_LOCK + drOrderNum,
                6, TimeUnit.SECONDS,
                () -> createCheckHistory(drUserInfoBo, drMemberBo, currentSeconds, drOrderNum, drCheckHousePutTo,
                        drCheckItemVos));
    }

    /**
     * @return com.deep.deepenterpise.common.result.DrResult
     * @Auth xyz
     * @Desc //TODO 创建入户检查历史记录
     * @Time 22:00 2024/6/13
     * @Param [drUserUuid, drUnitKey, drOrderNum, drCheckHousePutTo]
     */
    private DrResult createCheckHistory(DrUserInfoBo drUserInfoBo, DrMemberBo drMemberBo, Long drNowTime, String drOrderNum,
                                        DrCheckHousePutTo drCheckHousePutTo, List<DrUnitCheckItemVo> drCheckItemVos) {
        Long drNum = drCheckHistoryMapper.countByDrOrderNum(drOrderNum);
        if (drNum != null && drNum > 0) {
            return DrResult.error(DrCodeMsg.SYSTEM_BUSY_ERR);
        }

        DrContentTo drContent = drCheckHousePutTo.getDrContent();
        List<DrItemTo> drItemTos = drContent.getDrItem();
        List<DrItemTo> drUnItemTos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(drItemTos)) {
            List<Integer> drCheckItemIds = drItemTos.stream().map(DrItemTo::getDrId).collect(Collectors.toList());
            for (DrUnitCheckItemVo drCheckItemVo : drCheckItemVos) {
                if (!drCheckItemIds.contains(drCheckItemVo.getDrId())) {
                    drUnItemTos.add(new DrItemTo(drCheckItemVo));
                }
            }
        }

        DrCheckHistory drCheckHistory = new DrCheckHistory();
        drCheckHistory.setDrOrderNum(drCheckHousePutTo.getDrMasterOrderNum());
        drCheckHistory.setDrUrl(drCheckHousePutTo.getDrUrl());
        drCheckHistory.setDrCheckOrderNum(drOrderNum);
        drCheckHistory.setDrCheckPerson(drUserInfoBo.getDrUserUuid());
        drCheckHistory.setDrMember(drMemberBo.getDrId());
        drCheckHistory.setDrItem(DrGson.toJSONString(drUnItemTos));
        drCheckHistory.setDrContent(DrGson.toJSONString(drContent));
        drCheckHistory.setDrIsSafe(drCheckHousePutTo.getDrIsSafe());
        drCheckHistory.setDrUnitKey(drUserInfoBo.getDrUnitKey());
        drCheckHistory.setDrStatus(DrStateEnum.YES.getDrState());
        drCheckHistory.setDrCreateTime(drNowTime);

        return drTransactionCommon.execute("提交入户安检记录", () -> {
            drGoodsOrderMapper.updateByDrMasterOrderNum(drCheckHousePutTo.getDrMasterOrderNum(), drNowTime,
                    DrSecurityEnum.YES.getDrType(), DrPayStateEnum.SUCCESS.getDrState());
            drCheckHistoryMapper.insert(drCheckHistory);

            DrDangerHistoryTo drDangerHistoryTo = new DrDangerHistoryTo();
            drDangerHistoryTo.setDrIsSafe(drCheckHistory.getDrIsSafe());
            drDangerHistoryTo.setDrContent(drContent);
            drDangerHistoryTo.setDrOrderNum(drOrderNum);
            drDangerHistoryTo.setDrMemberId(drMemberBo.getDrId());
            drDangerHistoryTo.setDrMemberName(drMemberBo.getDrMemberName());
            drDangerHistoryTo.setDrMemberAddress(drMemberBo.getDrAddress());
            drDangerHistoryTo.setDrMemberPhone(drMemberBo.getDrMemberPhone());
            // 保存隐患记录，员工信息、隐患信息、订单号、创建时间、所有检查项
            addHouseDangerHistory(drUserInfoBo, drDangerHistoryTo, drOrderNum, drNowTime, drCheckItemVos);
        });
    }

    /**
     * @Auth xyz
     * @Desc //TODO 添加隐患记录
     * @Time 17:53 2024/6/24
     * @Param [drOrderNum, drCreateTime]
     */
    private void addHouseDangerHistory(DrUserInfoBo drUserInfoBo, DrDangerHistoryTo drDangerHistoryTo,
                                       String drOrderNum, long drNowTime, List<DrUnitCheckItemVo> drCheckItemVos) {
        // 验证订单是否已经存在
        DrDangerHistory dangerHistory = drDangerHistoryMapper.findByDrOrderNum(drOrderNum);
        if (dangerHistory != null) {
            return;
        }
        // 生成隐患单号
        String drDangerNum = DrOrderTypeEnum.DANGER_HOUSE.getDrCode() + drNowTime;
        drLockService.executeWithLock(DrLockConstants.CREATE_DANGER_HISTORY_LOCK + drDangerNum,
                6, TimeUnit.SECONDS,
                () -> iDrDangerService.saveDangerHistory(drUserInfoBo, drDangerHistoryTo,
                        DrCategoryEnum.CHECK_HOUSE.getDrType(), drOrderNum, drDangerNum, drNowTime, drCheckItemVos));
    }


    /**
     * @return com.deep.deepenterpise.common.result.DrResult
     * @Auth xyz
     * @Desc //TODO 获取检查项列表
     * @Time 11:17 2024/6/24
     * @Param [drCheckItemPageTo]
     */
    @Override
    public DrResult postDrCheckItemList(DrCheckItemPageTo drCheckItemPageTo) {
        // 获取总页数
        drCheckItemPageTo.setDrStatus(DrStateEnum.YES.getDrState());
        Long count = drCheckItemMapper.countByPage(drCheckItemPageTo);
        DrPageBaseVo drPageBaseVo = new DrPageBaseVo(drCheckItemPageTo.getDrPage(),
                drCheckItemPageTo.getDrSize(), count);
        if (count != null && count > 0) {
            RowBounds rowBounds = DrPageHelper
                    .getRowBounds(drCheckItemPageTo.getDrPage(), drCheckItemPageTo.getDrSize());
            List<DrCheckItemVo> drItemVos = drCheckItemMapper
                    .findByPage(rowBounds, drCheckItemPageTo);
            drPageBaseVo.setDrData(drItemVos);
        }
        return DrResult.ok().data(drPageBaseVo);
    }

    /**
     * @return com.deep.deepenterpise.common.result.DrResult
     * @Auth xyz
     * @Desc //TODO 获取安检列表
     * @Time 16:21 2024/6/24
     * @Param [drCheckPageTo]
     */
    @Override
    public DrResult postDrCheckList(DrCheckPageTo drCheckPageTo) {
        Integer drType = drCheckPageTo.getDrType();
        drType = DrStateEnum.YES.compare(drType) ? DrOrderTypeEnum.NORMAL.getDrType() :
                DrOrderTypeEnum.CHECK_HOUSE.getDrType();
        drCheckPageTo.setDrType(drType);

        Long count = drCheckHistoryMapper.countByPage(drCheckPageTo);
        DrPageBaseVo drPageBaseVo = new DrPageBaseVo(drCheckPageTo.getDrPage(), drCheckPageTo.getDrSize(), count);
        if (count == null || count == 0) {
            return DrResult.ok().data(drPageBaseVo);

        }
        RowBounds rowBounds = DrPageHelper.getRowBounds(drCheckPageTo.getDrPage(), drCheckPageTo.getDrSize());
        List<DrCheckVo> drCheckVos = drCheckHistoryMapper.findByPage(rowBounds, drCheckPageTo);
        if (CollectionUtils.isEmpty(drCheckVos)) {
            return DrResult.ok().data(drPageBaseVo);
        }
        for (DrCheckVo drCheckVo : drCheckVos) {
            DrContentTo drContent;
            try {
                drContent = DrGson.parseObject(drCheckVo.getDrContentStr(), DrContentTo.class);
            } catch (Exception e) {
                drCheckVo.setDrContentStr(null);
                continue;
            }
            drCheckVo.setDrContentStr(null);
            if (drContent == null) {
                continue;
            }
            List<DrItemTo> drItem = drContent.getDrItem();
            List<String> drPhotos = drContent.getDrPhoto();

            drCheckVo.setDrPhoto(drPhotos);
            drCheckVo.setDrItemVos(drItem);
        }
        drPageBaseVo.setDrData(drCheckVos);
        return DrResult.ok().data(drPageBaseVo);
    }
}
